package org.infodavid.common.impl.persistence;

import java.util.List;

import javax.persistence.PersistenceException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infodavid.common.IBuilder;
import org.infodavid.common.model.ModelFactory;
import org.infodavid.common.model.security.IAccessControlEntry;
import org.infodavid.common.model.security.IAccessControlList;
import org.infodavid.common.model.security.ISecuredObjectIdentifier;
import org.infodavid.common.model.security.ISecurityIdentifier;
import org.infodavid.common.persistence.AccessControlDataService;

/**
 * The Class AbstractAccessControlDataService.
 */
public abstract class AbstractAccessControlDataService extends AccessControlDataService {

  /** The Constant log. */
  private static final Log LOGGER = LogFactory.getLog(AbstractAccessControlDataService.class);

  /** The builder. */
  private final IBuilder<IAccessControlList> builder = ModelFactory.getInstance().getBuilder(
      IAccessControlList.class);

  /**
   * The Constructor.
   */
  protected AbstractAccessControlDataService() {
    super();
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDataService#create()
   */
  public IAccessControlList create() throws InstantiationException {
    return builder.create();
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDataService#copyTo(org.infodavid.common.model.IDataObject,
   * boolean, boolean)
   */
  public IAccessControlList copyTo(final IAccessControlList from, final boolean deep,
      final boolean asNew) throws PersistenceException, InstantiationException {
    final boolean isDebugEnabled = LOGGER.isDebugEnabled();

    if (isDebugEnabled) {
      LOGGER.debug("Copying entity from " + from + " using deep = " + deep + ", asNew = " + asNew);
    }

    final IAccessControlList to;

    if (from == null) {
      to = null;
    }
    else {
      to = builder.create();

      copyTo(from, to, asNew);
      to.setComment(from.getComment());
      to.setName(from.getName());
      to.setIdentifier(copyTo(from.getIdentifier()));
      copyTo(from.getEntries(), to.getEntries());
    }

    if (isDebugEnabled) {
      LOGGER.debug("Copied entity = " + to);
    }

    return to;
  }

  /**
   * Copy to.
   * @param from the from
   * @param to the to
   * @throws InstantiationException the instantiation exception
   */
  private void copyTo(final List<IAccessControlEntry> from, final List<IAccessControlEntry> to)
      throws InstantiationException {
    if (!(from == null || from.isEmpty())) {
      final IBuilder<IAccessControlEntry> entryBuilder =
          ModelFactory.getInstance().getBuilder(IAccessControlEntry.class);
      IAccessControlEntry toEntry;

      for (final IAccessControlEntry fromEntry : from) {
        toEntry = entryBuilder.create();

        toEntry.setObjectIdentifier(copyTo(fromEntry.getObjectIdentifier()));
        toEntry.getPermissions().putAll(fromEntry.getPermissions());
        to.add(toEntry);
      }
    }
  }

  /**
   * Copy to.
   * @param from the from
   * @return the i secured object identifier
   * @throws InstantiationException the instantiation exception
   */
  private ISecuredObjectIdentifier copyTo(final ISecuredObjectIdentifier from)
      throws InstantiationException {
    ISecuredObjectIdentifier to = null;

    if (from != null) {
      to = ModelFactory.getInstance().create(ISecuredObjectIdentifier.class);

      to.setIdentifier(from.getIdentifier());
      to.setType(from.getType());
    }

    return to;
  }

  /**
   * Copy to.
   * @param from the from
   * @return the i security identifier
   * @throws InstantiationException the instantiation exception
   */
  private ISecurityIdentifier copyTo(final ISecurityIdentifier from) throws InstantiationException {
    ISecurityIdentifier to = null;

    if (from != null) {
      to = ModelFactory.getInstance().create(ISecurityIdentifier.class);

      to.setRole(from.getRole());
      to.setGroup(from.getGroup());
      to.setUser(from.getUser());
    }

    return to;
  }

  /*
   * (non-Javadoc)
   * @see
   * org.infodavid.common.persistence.IDataService#copyListItemTo(org.infodavid.common.model.IDataObject
   * , boolean, boolean)
   */
  public IAccessControlList copyListItemTo(final IAccessControlList from, final boolean deep,
      final boolean asNew) throws PersistenceException, InstantiationException {
    return copyTo(from, deep, asNew);
  }
}
